﻿#ifndef __GAF_ARRAY_H__
#define __GAF_ARRAY_H__

namespace GAF
{
	//template<class T> class Struct -* _INTERFACE ForEach
		template<class T> class Array;
}
#define GAF_CArray			GAF::Array

#include "GAF_Struct.h"

#define GAF_ARY_SIZE			10
#define GAF_ARY_GROW			5

#define GAF_ARY_ALL			(int)-1
#define GAF_ARY_HEAD			(UINT)0
#define GAF_ARY_END			(UINT)-1

#include "GAF_MemManage.h"

namespace GAF
{
	/// 动态数组模板类
	template<class T>
	class Array : public Struct<T>
	{
	public:
		Array(UINT nInitSize = GAF_ARY_SIZE, UINT nGrow = GAF_ARY_GROW);
		virtual ~Array();

		/// 添加单个内容
		bool			Add(const T& tNew);
		/// 从其他数组中添加内容
		bool			Append(const Array& aOther, UINT nOtherID = GAF_ARY_HEAD, int nCount = GAF_ARY_ALL);
		/// 插入单个内容
		bool			Insert(UINT nID, const T& tNew);	// 插入到指定ID之前
		/// 从其他数组中插入内容
		bool			Insert(UINT nID, const Array& aOther, UINT nOtherID = GAF_ARY_HEAD, int nCount = GAF_ARY_ALL);
		/// 移除内容
		bool			Remove(UINT nID, int nCount = 1);	// 移除指定ID后的一定长度的节点
		/// 清除全部内容
		bool			Clean(T* ptReturn = NULL);	// 清除全部节点
		/// 清除并销毁
		bool			Destroy(T* ptReturn = NULL);	// 完全清除释放内存

		/// 从其他数组复制内容
		bool			CopyFrom(Array& aFrom, UINT nFromID = GAF_ARY_HEAD, UINT nToID = GAF_ARY_END, int nCount = GAF_ARY_ALL);
		/// 复制内容到其他数组
		bool			CopyTo(Array& aTo, UINT nFromID = GAF_ARY_HEAD, UINT nToID = GAF_ARY_END, int nCount = GAF_ARY_ALL);
		/// 从其他数组移动内容
		bool			MoveForm(Array& aFrom, UINT nFromID = GAF_ARY_HEAD, UINT nToID = GAF_ARY_END, int nCount = GAF_ARY_ALL);
		/// 移动内容到其他数组
		bool			MoveTo(Array& aTo, UINT nFromID = GAF_ARY_HEAD, UINT nToID = GAF_ARY_END, int nCount = GAF_ARY_ALL);

		/// 设置指定序号中的内容
		bool			SetAt(UINT nID, const T& tNew);
		/// 获得指定序号中的内容
		T&			GetAt(UINT nID);

		Pointer			Foreach(bool bFirst);
		UINT			GetCount();

		/// 设置动态数组每次增加数
		void			SetGrow(UINT nNum);		// 设置每次增加数
		/// 释放大于当前上界的未使用的内存
		bool			FreeExtra();			// 释放大于当前上界的未使用的内存
	public:
		T&			operator[](int nID);

	protected:
		/// 扩展动态数组
		void			Enlarge();			// 扩展

	private:
		bool			Check(const Array* aOne);
		bool			Check(const Array* aOne, UINT& nID);
		bool			Check(const Array* aOne, UINT& nID, int& nCount);

	protected:
		/// 数组
		T*			m_ptArray;
		/// 初始大小
		UINT			m_nInitSize;
		/// 总大小
		UINT			m_nSize;
		/// 每次增加数
		UINT			m_nGrow;
		/// 当前大小
		UINT			m_nLength;
	private:
		/// 遍历循环的当前序号
		UINT			m_nCurID;
	};




	template<class T>
	Array<T>::Array(UINT nInitSize, UINT nGrow)
	{
		m_ptArray	= NULL;
		m_nInitSize	= nInitSize;
		m_nSize		= 0;
		m_nGrow		= nGrow;
		m_nLength	= 0;
		m_nCurID	= 0;
	}

	template<class T>
	Array<T>::~Array()
	{
		Destroy();
	}

	template<class T>
	bool Array<T>::Add(const T& tNew)
	{
		if(m_nLength >= m_nSize)
			Enlarge();

		_MEMCPY(m_ptArray + m_nLength, &tNew, sizeof(T));
		m_nLength++;

		return true;
	}

	template<class T>
	bool Array<T>::Append(const Array& aOther, UINT nOtherID, int nCount)
	{
		if(!Check(&aOther, nOtherID, nCount))
			return false;

		while(m_nLength + nCount > m_nSize)
			Enlarge();

		_MEMCPY(m_ptArray + m_nLength, aOther.m_ptArray + nOtherID, sizeof(T) * nCount);
		m_nLength += nCount;

		return true;
	}

	template<class T>
	bool Array<T>::Insert(UINT nID, const T& tNew)
	{
		if(!Check(this, nID))
			return false;

		if(m_nLength + 1 >= m_nSize)
			Enlarge();

		int nLastLength = m_nLength - nID;
		if(nLastLength > 0)
		{
			_MEMMOVE(m_ptArray + nID + 1, m_ptArray + nID, sizeof(T) * nLastLength);
		}
		_MEMCPY(m_ptArray + nID, &tNew, sizeof(T));
		m_nLength += 1;

		return true;
	}

	template<class T>
	bool Array<T>::Insert(UINT nID, const Array& aOther, UINT nOtherID, int nCount)
	{
		if(!Check(this, nID))
			return false;
		if(!Check(&aOther, nOtherID, nCount))
			return false;

		while(m_nLength + nCount >= m_nSize)
			Enlarge();

		int nLastLength = m_nLength - nID;
		if(nLastLength > 0)
		{
			_MEMMOVE(m_ptArray + nID + nCount, m_ptArray + nID, sizeof(T) * nLastLength);
		}
		_MEMCPY(m_ptArray + nID, aOther.m_ptArray + nOtherID, sizeof(T) * nCount);
		m_nLength += nCount;

		return true;
	}

	template<class T>
	bool Array<T>::Remove(UINT nID, int nCount)
	{
		if(!Check(this, nID, nCount))
			return false;

		for(int i = 0; i < nCount; i++)
			m_ptArray[nID + i].~T();
		_MEMSET(m_ptArray + nID, 0, sizeof(T) * nCount);

		int nLastLength = m_nLength - (nID + nCount);
		if(nLastLength > 0)
		{
			_MEMMOVE(m_ptArray + nID, m_ptArray + nID + nCount, sizeof(T) * nLastLength);
			_MEMSET(m_ptArray + nID + nLastLength, 0, sizeof(T) * nCount);
		}

		m_nLength -= nCount;

		return true;
	}

	template<class T>
	bool Array<T>::Clean(T* ptReturn)
	{
		if(ptReturn != NULL)
		{
			for(UINT i = 0; i < m_nLength; i++)
				// catch
				_MEMCPY(&ptReturn[i], m_ptArray + i, sizeof(T));
		}

		return Remove(GAF_ARY_HEAD, GAF_ARY_ALL);
	}

	template<class T>
	bool Array<T>::Destroy(T* ptReturn)
	{
		if(!Clean(ptReturn))
			return false;

		if(m_ptArray != NULL)
			GAF_DELETE_ARY(m_ptArray);

		m_nLength = m_nSize = 0;
		return true;
	}

	template<class T>
	bool Array<T>::CopyFrom(Array& aFrom, UINT nFromID, UINT nToID, int nCount)
	{
		return Insert(nToID, aFrom, nFromID, nCount);
	}

	template<class T>
	bool Array<T>::CopyTo(Array& aTo, UINT nFromID, UINT nToID, int nCount)
	{
		return aTo.CopyFrom(*this, nFromID, nToID, nCount);
	}

	template<class T>
	bool Array<T>::MoveForm(Array& aFrom, UINT nFromID, UINT nToID, int nCount)
	{
		if(!Insert(nToID, aFrom, nFromID, nCount))
			return false;
		return aFrom.Remove(nFromID, nCount);
	}

	template<class T>
	bool Array<T>::MoveTo(Array& aTo, UINT nFromID, UINT nToID, int nCount)
	{
// 		if(!aTo.Insert(nToID, *this, nFromID, nCount))
// 			return false;
// 		return Remove(nFromID, nCount);
		return aTo.MoveForm(*this, nFromID, nToID, nCount);
	}

	template<class T>
	bool Array<T>::SetAt(UINT nID, const T& tNew)
	{
		if(!Check(this, nID))
			return false;

		_MEMCPY(m_ptArray + nID, &tNew, sizeof(T));
		return true;
	}

	template<class T>
	T& Array<T>::GetAt(UINT nID)
	{
		if(nID >= m_nLength)
			nID = m_nLength - 1;

		return m_ptArray[nID];
	}

	template<class T>
	Pointer Array<T>::Foreach(bool isFirst)
	{
		if(isFirst)
			m_nCurID = 0;

		if(m_nCurID >= m_nLength)
			return NULL;

		return (Pointer)(&m_ptArray[m_nCurID++]);
	}

	template<class T>
	void Array<T>::SetGrow(UINT nNum)
	{
		if(nNum > 0)
			m_nGrow = nNum;
	}

	template<class T>
	UINT Array<T>::GetCount()
	{
		return m_nLength;
	}

	template<class T>
	T& Array<T>::operator[](int nID)
	{
		return GetAt((UINT)nID);
	}

	template<class T>
	void Array<T>::Enlarge()
	{
		if(m_nSize <= 0)
			m_nSize = m_nInitSize;
		else
			m_nSize += m_nGrow;

		T* ptNewArray = GAF_NEW_ARY(T, m_nSize);
		_MEMSET(ptNewArray, 0, sizeof(T) * m_nSize);
		_MEMCPY(ptNewArray, m_ptArray, sizeof(T) * m_nLength);

		if(m_ptArray != NULL)
			GAF_DELETE_ARY(m_ptArray);
		m_ptArray = ptNewArray;
	}

	template<class T>
	bool Array<T>::Check(const Array* aOne)
	{
		return (aOne->m_ptArray == NULL) ? false : true;
	}

	template<class T>
	bool Array<T>::Check(const Array* aOne, UINT& nID)
	{
		if(nID == GAF_ARY_HEAD)
			nID = 0;
		else if(nID == GAF_ARY_END)
			nID = aOne->m_nLength;

		if(nID > aOne->m_nLength)
			return false;
		return true;
	}

	template<class T>
	bool Array<T>::Check(const Array* aOne, UINT& nID, int& nCount)
	{
		if(!Check(aOne, nID))
			return false;

		if(nCount == GAF_ARY_ALL) nCount = aOne->m_nLength;

		if(nID + nCount > aOne->m_nLength)
			nCount = aOne->m_nLength - nID;

		return true;
	}

//****
}

#endif
